﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;

namespace Remote_Desktop_Administrator
{
    //
    // Got code snippets for encryption from - http://support.microsoft.com/kb/307010 
    //
    static class Encryption
    {
        //  Call this function to remove the key from memory after use for security
        [System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory")]
        public static extern bool ZeroMemory(IntPtr Destination, int Length);

        public static string strSecretKey = "";
        public static string strFileIn = "";
        public static string strFileOut = "";

        //
        // Overview: pads or fixes secrect key that is over or under 8 characters
        // Got this idea from - http://www.osix.net/modules/article/?id=100
        //
        public static void FixSecretKey(string password)
        {
            if (password.Length > 8)
                password = password.Substring(0, 8);
            else if (password.Length < 8)
            {
                int add = 8 - password.Length;
                for (int i = 0; i < add; i++)
                    password = password + i;
            }

            strSecretKey = password;
        }

        public static void EncryptFile()
        {
            // For additional security, pin the key.
            GCHandle gch = GCHandle.Alloc(strSecretKey, GCHandleType.Pinned);

            FileStream fsInput = new FileStream(strFileIn, FileMode.Open, FileAccess.Read);
            
            FileStream fsEncrypted = new FileStream(strFileOut, FileMode.Create, FileAccess.Write);
            DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
            DES.Key = ASCIIEncoding.ASCII.GetBytes(strSecretKey);
            DES.IV = ASCIIEncoding.ASCII.GetBytes(strSecretKey);
            ICryptoTransform desencrypt = DES.CreateEncryptor();
            CryptoStream cryptostream = new CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write);

            byte[] bytearrayinput = new byte[fsInput.Length];
            fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
            cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
            cryptostream.Close();
            fsInput.Close();
            fsEncrypted.Close();
            
            // delete unencrypted file
            File.Delete(strFileIn);

            // Remove the key from memory. 
            ZeroMemory(gch.AddrOfPinnedObject(), strSecretKey.Length * 2);
            gch.Free();
        }

        public static void DecryptFile()
        {
            // For additional security, pin the key.
            GCHandle gch = GCHandle.Alloc(strSecretKey, GCHandleType.Pinned);

            DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
            //A 64 bit key and IV is required for this provider.
            //Set secret key For DES algorithm.
            DES.Key = ASCIIEncoding.ASCII.GetBytes(strSecretKey);
            //Set initialization vector.
            DES.IV = ASCIIEncoding.ASCII.GetBytes(strSecretKey);

            //Create a file stream to read the encrypted file back.
            FileStream fsread = new FileStream(strFileIn, FileMode.Open, FileAccess.Read);
            //Create a DES decryptor from the DES instance.
            ICryptoTransform desdecrypt = DES.CreateDecryptor();
            //Create crypto stream set to read and do a DES decryption transform on incoming bytes.
            CryptoStream cryptostreamDecr = new CryptoStream(fsread, desdecrypt, CryptoStreamMode.Read);
            //Create file system object to support output
            StreamWriter fsDecrypted = new StreamWriter(strFileOut);
            try
            {
                //Print the contents of the decrypted file.
                fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
                fsDecrypted.Flush();
                fsDecrypted.Close();
                fsread.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error while attempting to decrypt settings file - " + ex.Message + "\nVerify you are using the correct key.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                fsDecrypted.Close();
                fsread.Close();
            }

            // Remove the key from memory. 
            ZeroMemory(gch.AddrOfPinnedObject(), strSecretKey.Length * 2);
            gch.Free();
        }
    }
}
